package pcvc.server;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import net.java.dev.eval.Expression;

import org.osoa.sca.annotations.Init;
import org.osoa.sca.annotations.Reference;
import org.osoa.sca.annotations.Scope;

import pcvc.common.classes.PCVCAbstractObserver;
import pcvc.common.classes.Question;
import pcvc.common.classes.StudentAnswer;
import pcvc.common.services.IPCVCObserverService;
import pcvc.common.services.IPCVCServerStudentService;
import pcvc.common.services.IPCVCServerTeacherService;
import pcvc.common.services.IPCVCSubject;


@Scope("CONVERSATION")
public class PCVCServer implements IPCVCServerStudentService, IPCVCSubject
{
	@Reference(name="observerService1")
	private IPCVCObserverService pcvcStudent1;
	@Reference(name="observerService2")
	private IPCVCObserverService pcvcStudent2;
	@Reference(name="observerService3")
	private IPCVCObserverService pcvcStudent3;
	@Reference(name="observerService4")
	private IPCVCObserverService pcvcStudent4;

	@Reference(name="observerTeacher")
	private IPCVCObserverService pcvcTeacher;

	private List<String> comments;

	public List<PCVCAbstractObserver> observers;
	private Map<Integer,IPCVCObserverService> observerServices;

	public Question currentQuestion;
	public List<Question> finishedQuestions;


	public PCVCServer( )
	{
		System.out.println("Starting server...");
		currentQuestion = null;
		comments = new ArrayList<String>( );
		observers = new ArrayList<PCVCAbstractObserver>( );
		observerServices = new LinkedHashMap<Integer,IPCVCObserverService>();
		finishedQuestions = new ArrayList<Question>( );
	}

	/**
	 * Adds a comments to the list of comments
	 * @param comment The comment to be added
	 */
	@Override
	public synchronized void addComment( String comment )
	{
		comments.add( comment );
		notifyObservers( );
	}

	/**
	 * Adds a student answer to the current question
	 * @param studentAnswer
	 */
	@Override
	public void addStudentAnswer( StudentAnswer studentAnswer )
	{
		if( currentQuestion != null )
		{
			currentQuestion.getCorrectAnswer( );
		}

		notifyObservers( );
	}

	/**
	 * Returns the answers of the current question given by the students
	 */
	@Override
	public Set<StudentAnswer> getAnswers( )
	{
		Set<StudentAnswer> resp = null;

		if( currentQuestion != null )
		{
			resp = currentQuestion.getStudentsAnswers( );
		}

		return resp;
	}

	/**
	 * 
	 */
	@Override
	public String getCurrentQuestion( )
	{
		String resp = "There isn't a question to be answered yet.";

		if( currentQuestion != null )
		{
			resp = "Q" + currentQuestion.getNumber( ) + ": " + currentQuestion.getQuestion( ) + "\n Equation: " + currentQuestion.getEquation( );
		}

		return resp;
	}

	public void sendQuestion( Question question )
	{
		finishedQuestions.add( currentQuestion );
		currentQuestion = question;
		notifyObservers( );

		currentQuestion.setCorrectAnswer(PCVCCalculator.getInstance( ).evaluateQuestion( currentQuestion ));
	}

	@Override
	public List<String> getComments( )
	{
		return comments;
	}

	public StudentAnswer getAnswer( int studentId )
	{
		StudentAnswer resp = null;

		if( currentQuestion != null )
		{
			Iterator<StudentAnswer> iterator = currentQuestion.getStudentsAnswers( ).iterator( );

			while(iterator.hasNext( ))
			{
				if(iterator.next( ).getStudentId( ) == studentId)
				{
					resp = iterator.next( );
				}
			}
		}

		return resp;
	}

	@Override
	public void attach( PCVCAbstractObserver observer )
	{
		observers.add( observer );

		int id = observer.getId();

		switch(id)
		{
		case 1: observerServices.put(observer.getId(), pcvcStudent1);
		break;
		case 2: observerServices.put(observer.getId(), pcvcStudent2);
		break;
		case 3: observerServices.put(observer.getId(), pcvcStudent3);
		break;
		case 4: observerServices.put(observer.getId(), pcvcStudent4);
		break;
		case 5: observerServices.put(observer.getId(), pcvcTeacher);
		break;

		}


	}

	@Override
	public void detach( PCVCAbstractObserver observer )
	{
		observers.remove( observer );

		observerServices.remove(observer.getId());
	}

	@Override
	public void notifyObservers( )
	{


		for (IPCVCObserverService service : observerServices.values()) {

			service.update();
			System.out.println("updating teacher...");

		}
	}



}